﻿using System;
using System.Net;
using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;

using Urd.Common;
using Urd.Packet;

namespace Urd.Workers
{
    public class position:worker
    {
        
        int packet_counter;
        const int packetdelay = 2;
        System.Globalization.CultureInfo culture;
     /// <summary>
     /// отправляемый пакет есть изначально тот который гет_неар возможно класс стоит сделать СТАТИК
     /// и считать количество записей. а отдавать всегда готовый пакет
     /// </summary>
     /// <param name="c"></param>
     /// <param name="p"></param>
     /// <returns></returns>
        public override packet process( cache c ,packet p = null)
        {
            

            DateTime timestart = DateTime.Now;
            
            packet_counter++;
            update(c);

            //to remake this ---acceptable
            if (p != null)
            {
                if (p.code == opcode_to_accept)
                {
                    packet newpacket = new packet(opcode_to_accept);

                    switch (p.command)
                    {
                        //#region getnear
                        //case Command.GetNear:

                        //    float dist = 80f;
                        //    object[] tempn = c.Sql("select id, x, y, z from position where id=" + p.GetInt(0).ToString(), true);
                        //    if (tempn.Length == 4 && tempn[0] != null)
                        //    {
                        //        float x = Convert.ToSingle(tempn[1]);
                        //        float y = Convert.ToSingle(tempn[2]);
                        //        float z = Convert.ToSingle(tempn[3]);

                        //        object[] temp2 = c.Sql(
                        //            "create table near as select id from position where"
                        //            + " abs(x)-abs(" + x.ToString() + ")<" + dist.ToString() + " and "
                        //            + " abs(y)-abs(" + y.ToString() + ")<" + dist.ToString() + " and "
                        //            + " abs(x)-abs(" + z.ToString() + ")<" + dist.ToString()
                        //            , true);
                        //        temp2 = c.Sql("select * from near", true);

                        //        List<byte> posn = new List<byte>();
                        //        posn.Add((byte)opcode_to_accept);
                        //        posn.Add((byte)Command.GetOK);
                        //        posn.Add((byte)0);
                        //        for (int i = 1; i < temp2.Length; i++)
                        //        {
                        //            object[] posp = c.Sql("select * from near where id=" + temp2[i].ToString(), true);
                        //            if (posp.Length == 4 && posp[0] != null)
                        //            {
                        //                int id = (int)posp[0];
                        //                float posx = Convert.ToSingle(posp[1]);
                        //                float posy = Convert.ToSingle(posp[2]);
                        //                float posz = Convert.ToSingle(posp[3]);
                        //                XYZ pp = new XYZ(id, posx, posy, posz);
                        //                posn.AddRange(pp.bytes);
                        //                //newpacket.Push((int)temp2[i]);
                        //            }

                        //        }
                        //        newpacket = new packet(posn.ToArray());
                        //        c.Sql("drop table near", true);
                        //        timespan = DateTime.Now - timestart;
                        //        debug.Log("[pos][getnear]" + timespan.ToString(), debug.loglevel.Status);

                        //        return newpacket;
                        //    }
                        //    else return new packet(Opcode.Error, Command.GetNear);


                        //#endregion
                        #region get
                        //get must add packet to getnear?
                        case Command.Get:
                            return cachedpacket;
                        ////packet newpacket = new packet(opcode_to_accept);

                        //object[] tempg = c.Sql("select id, x, y, z from position where id=" + p.GetInt(0).ToString(), true);

                        //if (tempg.Length == 4 && tempg[0] != null)
                        //{
                        //    newpacket.Push((int)tempg[0]);
                        //    debug.Log(tempg[0].ToString(), debug.loglevel.Errors);
                        //    newpacket.Push(Convert.ToSingle(tempg[1]));
                        //    newpacket.Push(Convert.ToSingle(tempg[2]));
                        //    newpacket.Push(Convert.ToSingle(tempg[3]));
                        //    timespan = DateTime.Now - timestart;
                        //    debug.Log("[pos][get]" + timespan.ToString(), debug.loglevel.Status);
                        //    return newpacket;
                        //}
                        //else
                        //{
                        //    newpacket = new packet(Opcode.Error);
                        //    newpacket.Push(p.ID);
                        //    return newpacket;
                        //}
                        // break;
                        #endregion
                        #region set
                        case Command.Set:



                            object[] temps =
                                c.Sql
                                ("update "+name+" set " +
                                "x=" + p.GetFloat(1).ToString(culture) + ", " +
                                "y=" + p.GetFloat(2).ToString(culture) + ", " +
                                "z=" + p.GetFloat(3).ToString(culture) + " " +
                                "where id=" + p.GetInt(0).ToString(), false);

                            if (temps.Length == 1 && temps[0] != null)
                            {


                                //newpacket.Push(p.ID);
                                //newpacket.Push(Convert.ToSingle(temps[0]));
                                newpacket.command = Command.None;
                                return newpacket;
                            }
                            else
                            {
                                newpacket = new packet(opcode_to_accept, Command.None);
                                //newpacket.Push(p.ID);
                                return newpacket;
                            }


                        #endregion
                        #region new
                        case Command.New:
                            float xn = p.GetFloat(1);
                            float yn = p.GetFloat(2);
                            float zn = p.GetFloat(3);

                            object[] tempnew = c.Sql("select min(id)-1 from " + name, true);
                            int min = 0;
                            min = Convert.ToInt32(tempnew[0]);
                            tempnew = c.Sql
                                ("insert into "+name+" values("
                                + min + "," + xn.ToString(culture) + ","
                                + yn.ToString(culture) + ","
                                + zn.ToString(culture) + ")", false);

                            newpacket.Push(min);

                            return newpacket;
                        #endregion
                        default:
                            return new packet(opcode_to_accept, Command.None);
                    }
                }
                else return new packet(Opcode.Error, Command.WrongManager);
            }
            else return new packet(Opcode.Error, Command.None);
            

               
        }

        private void update(cache c) 
        {
            DateTime timestart = DateTime.Now;
            TimeSpan timespan;
            if (packet_counter > packetdelay)
            {
                packet_counter = 0;

                packet newpacket;
                object[] temp2 = c.Sql("select * from " + name, true);

                List<byte> posn = new List<byte>();
                posn.Add((byte)opcode_to_accept);
                posn.Add((byte)Command.GetOK);
                posn.Add((byte)temp2.Length);

                for (int i = 0; i < temp2.Length-3; i+=4)
                {
                   // object[] posp = c.Sql("select * from position where id=" + temp2[i].ToString(), true);
                   // if (posp.Length == 4 && posp[0] != null)
                   // {
                        int id = (int)temp2[i+0];
                        float posx = Convert.ToSingle(temp2[i + 1]);
                        float posy = Convert.ToSingle(temp2[i + 2]);
                        float posz = Convert.ToSingle(temp2[i + 3]);
                        XYZ pp = new XYZ(id, posx, posy, posz);
                        posn.AddRange(pp.bytes);
                        //newpacket.Push((int)temp2[i]);
                   // }

                }
                newpacket = new packet(posn.ToArray());
                // c.Sql("drop table near", true);
                timespan = DateTime.Now - timestart;
                debug.Log("["+name+"][update]" + timespan.ToString(), debug.loglevel.Status);

                this.cachedpacket = newpacket;
            }
        }

        public position():base()
        {
            

           culture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            culture.NumberFormat.NumberDecimalSeparator = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = culture;

            cachedpacket = new packet(Opcode.Pos, Command.None);
        }
    }

    public class positionr : worker
    {

        int packet_counter;
        const int packetdelay = 2;
        System.Globalization.CultureInfo culture;
        /// <summary>
        /// отправляемый пакет есть изначально тот который гет_неар возможно класс стоит сделать СТАТИК
        /// и считать количество записей. а отдавать всегда готовый пакет
        /// </summary>
        /// <param name="c"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public override packet process(cache c, packet p = null)
        {


            DateTime timestart = DateTime.Now;

            packet_counter++;
            update(c);

            //to remake this ---acceptable
            if (p != null)
            {
                if (p.code == opcode_to_accept)
                {
                    packet newpacket = new packet(opcode_to_accept);

                    switch (p.command)
                    {
                        //#region getnear
                        //case Command.GetNear:

                        //    float dist = 80f;
                        //    object[] tempn = c.Sql("select id, x, y, z from position where id=" + p.GetInt(0).ToString(), true);
                        //    if (tempn.Length == 4 && tempn[0] != null)
                        //    {
                        //        float x = Convert.ToSingle(tempn[1]);
                        //        float y = Convert.ToSingle(tempn[2]);
                        //        float z = Convert.ToSingle(tempn[3]);

                        //        object[] temp2 = c.Sql(
                        //            "create table near as select id from position where"
                        //            + " abs(x)-abs(" + x.ToString() + ")<" + dist.ToString() + " and "
                        //            + " abs(y)-abs(" + y.ToString() + ")<" + dist.ToString() + " and "
                        //            + " abs(x)-abs(" + z.ToString() + ")<" + dist.ToString()
                        //            , true);
                        //        temp2 = c.Sql("select * from near", true);

                        //        List<byte> posn = new List<byte>();
                        //        posn.Add((byte)opcode_to_accept);
                        //        posn.Add((byte)Command.GetOK);
                        //        posn.Add((byte)0);
                        //        for (int i = 1; i < temp2.Length; i++)
                        //        {
                        //            object[] posp = c.Sql("select * from near where id=" + temp2[i].ToString(), true);
                        //            if (posp.Length == 4 && posp[0] != null)
                        //            {
                        //                int id = (int)posp[0];
                        //                float posx = Convert.ToSingle(posp[1]);
                        //                float posy = Convert.ToSingle(posp[2]);
                        //                float posz = Convert.ToSingle(posp[3]);
                        //                XYZ pp = new XYZ(id, posx, posy, posz);
                        //                posn.AddRange(pp.bytes);
                        //                //newpacket.Push((int)temp2[i]);
                        //            }

                        //        }
                        //        newpacket = new packet(posn.ToArray());
                        //        c.Sql("drop table near", true);
                        //        timespan = DateTime.Now - timestart;
                        //        debug.Log("[pos][getnear]" + timespan.ToString(), debug.loglevel.Status);

                        //        return newpacket;
                        //    }
                        //    else return new packet(Opcode.Error, Command.GetNear);


                        //#endregion
                        #region get
                        //get must add packet to getnear?
                        case Command.Get:
                            return cachedpacket;
                        ////packet newpacket = new packet(opcode_to_accept);

                        //object[] tempg = c.Sql("select id, x, y, z from position where id=" + p.GetInt(0).ToString(), true);

                        //if (tempg.Length == 4 && tempg[0] != null)
                        //{
                        //    newpacket.Push((int)tempg[0]);
                        //    debug.Log(tempg[0].ToString(), debug.loglevel.Errors);
                        //    newpacket.Push(Convert.ToSingle(tempg[1]));
                        //    newpacket.Push(Convert.ToSingle(tempg[2]));
                        //    newpacket.Push(Convert.ToSingle(tempg[3]));
                        //    timespan = DateTime.Now - timestart;
                        //    debug.Log("[pos][get]" + timespan.ToString(), debug.loglevel.Status);
                        //    return newpacket;
                        //}
                        //else
                        //{
                        //    newpacket = new packet(Opcode.Error);
                        //    newpacket.Push(p.ID);
                        //    return newpacket;
                        //}
                        // break;
                        #endregion
                        #region set
                        case Command.Set:



                            object[] temps =
                                c.Sql
                                ("update " + name + " set " +
                                "x=" + p.GetFloat(1).ToString(culture) + ", " +
                                "y=" + p.GetFloat(2).ToString(culture) + ", " +
                                "z=" + p.GetFloat(3).ToString(culture) + ", " +
                                "r=" + p.GetFloat(4).ToString(culture) + " " +
                                "where id=" + p.GetInt(0).ToString(), false);

                            if (temps.Length == 1 && temps[0] != null)
                            {


                                //newpacket.Push(p.ID);
                                //newpacket.Push(Convert.ToSingle(temps[0]));
                                newpacket.command = Command.None;
                                return newpacket;
                            }
                            else
                            {
                                newpacket = new packet(opcode_to_accept, Command.None);
                                //newpacket.Push(p.ID);
                                return newpacket;
                            }


                        #endregion
                        #region new
                        case Command.New:
                            float xn = p.GetFloat(1);
                            float yn = p.GetFloat(2);
                            float zn = p.GetFloat(3);
                            float rn = p.GetFloat(4);

                        
                            object[] tempnew = c.Sql
                                ("insert into " + name + "(x,y,z,r) values("                                
                                + xn.ToString(culture) + ","
                                + yn.ToString(culture) + ","
                                + zn.ToString(culture) + ","
                                + rn.ToString(culture) + ")"
                                , false);

                            

                            return new packet(opcode_to_accept, Command.New);
                        #endregion
                        default:
                            return new packet(opcode_to_accept, Command.None);
                    }
                }
                else return new packet(Opcode.Error, Command.WrongManager);
            }
            else return new packet(Opcode.Error, Command.None);



        }

        private void update(cache c)
        {
            DateTime timestart = DateTime.Now;
            TimeSpan timespan;
            if (packet_counter > packetdelay)
            {
                packet_counter = 0;

                packet newpacket;
                object[] temp2 = c.Sql("select * from " + name, true);

                List<byte> posn = new List<byte>();
                posn.Add((byte)opcode_to_accept);
                posn.Add((byte)Command.GetOK);
                posn.Add((byte)temp2.Length);

                for (int i = 0; i < temp2.Length - 4; i += 5)
                {
                    // object[] posp = c.Sql("select * from position where id=" + temp2[i].ToString(), true);
                    // if (posp.Length == 4 && posp[0] != null)
                    // {
                    int id = Convert.ToInt32(temp2[i + 0]);
                    float posx = Convert.ToSingle(temp2[i + 1]);
                    float posy = Convert.ToSingle(temp2[i + 2]);
                    float posz = Convert.ToSingle(temp2[i + 3]);
                    float posr = Convert.ToSingle(temp2[i + 4]);
                    XYZR pp = new XYZR(id, posx, posy, posz,posr);
                    posn.AddRange(pp.bytes);
                    //newpacket.Push((int)temp2[i]);
                    // }

                }
                newpacket = new packet(posn.ToArray());
                // c.Sql("drop table near", true);
                timespan = DateTime.Now - timestart;
                debug.Log("[" + name + "][update]" + timespan.ToString(), debug.loglevel.Status);

                this.cachedpacket = newpacket;
            }
        }

        public positionr()
            : base()
        {


            culture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            culture.NumberFormat.NumberDecimalSeparator = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = culture;

            cachedpacket = new packet(Opcode.Pos, Command.None);
        }
    }
}
